<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<script src="../dist/iife/spine-webgl.js"></script>
<link rel="stylesheet" href="../../index.css">

<body>
	<div class="overlay" style="user-select: none;">
		<span>Drag anywhere</span>
		<span id="fps"></span>
		<button id="fullscreen" class="btn">Fullscreen</div>
	</div>
	<canvas id="canvas" style="position: absolute; width: 100%; height: 100vh;"></canvas>
	<script>
		class App {
			constructor() {
				this.skeleton = null;
				this.animationState = null;
				this.fps = document.body.querySelector("#fps");
				const fsButton = document.body.querySelector("#fullscreen");
				let fsEnabled = false;
				fsButton.addEventListener("click", () => {
					if (fsEnabled) {
						document.exitFullscreen();
						fsButton.innerText = "Fullscreen"
					} else {
						document.body.requestFullscreen()
						fsButton.innerText = "Windowed";
					}
					fsEnabled = !fsEnabled;
				})
			}

			loadAssets(canvas) {
				// Load the skeleton file.
				canvas.assetManager.loadBinary("/assets/celestial-circus-pro.skel");
				// Load the atlas and its pages.
				canvas.assetManager.loadTextureAtlas("/assets/celestial-circus-pma.atlas");
			}

			initialize(canvas) {
				let assetManager = canvas.assetManager;

				// Create the texture atlas.
				var atlas = assetManager.require("/assets/celestial-circus-pma.atlas");

				// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
				var atlasLoader = new spine.AtlasAttachmentLoader(atlas);

				// Create a SkeletonBinary instance for parsing the .skel file.
				var skeletonBinary = new spine.SkeletonBinary(atlasLoader);

				// Set the scale to apply during parsing, parse the file, and create a new skeleton.
				skeletonBinary.scale = 0.5;
				var skeletonData = skeletonBinary.readSkeletonData(assetManager.require("/assets/celestial-circus-pro.skel"));
				this.skeleton = new spine.Skeleton(skeletonData);

				// Create an AnimationState, and set the "run" animation in looping mode.
				var animationStateData = new spine.AnimationStateData(skeletonData);
				this.animationState = new spine.AnimationState(animationStateData);
				this.animationState.setAnimation(0, "eyeblink-long", true);

				// Center the camera on the skeleton
				const offset = new spine.Vector2();
				const size = new spine.Vector2();
				this.skeleton.setToSetupPose();
				this.skeleton.update(0);
				this.skeleton.updateWorldTransform(spine.Physics.update);
				this.skeleton.getBounds(offset, size);
				canvas.renderer.camera.position.x = offset.x + size.x / 2;
				canvas.renderer.camera.position.y = offset.y + size.y / 2;

				// Setup an input listener on the canvas to process touch/mouse events. Allow drawing the skeleton around
				// by clicking and dragging anywhere on the canvas.
				let lastX = -1, lastY = -1;
                canvas.input.addListener({
                    down: (x, y) => {
                        // Calculate the mouse position in the coordinate space of the camera, aka world space.
                        // The skeleton and its bones live in the same coordinate space.
                        let mousePosition = new spine.Vector3(x, y);
                        canvas.renderer.camera.screenToWorld(mousePosition, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);

                        lastX = mousePosition.x;
						lastY = mousePosition.y;
                    },
                    dragged: (x, y) => {
                        // Calculate the mouse position in the coordinate space of the camera, aka world space.
                        // The skeleton and its bones live in this coordinate space.
                        let mousePosition = new spine.Vector3(x, y);
                        canvas.renderer.camera.screenToWorld(mousePosition, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);

						this.skeleton.x += mousePosition.x - lastX;
						this.skeleton.y += mousePosition.y - lastY;

						lastX = mousePosition.x;
						lastY = mousePosition.y;
                    }
                })
			}

			update(canvas, delta) {
				// Update the animation state using the delta time.
				this.animationState.update(delta);
				// Apply the animation state to the skeleton.
				this.animationState.apply(this.skeleton);
				// Let the skeleton update the transforms of its bones and apply physics
				this.skeleton.update(delta);
				this.skeleton.updateWorldTransform(spine.Physics.update);

				this.fps.innerText = canvas.time.framesPerSecond.toFixed(2) + " fps";
			}

			render(canvas) {
				let renderer = canvas.renderer;
				// Resize the viewport to the full canvas.
				renderer.resize(spine.ResizeMode.Expand);

				// Clear the canvas with a light gray color.
				canvas.clear(0.2, 0.2, 0.2, 1);

				// Begin rendering.
				renderer.begin();
				// Draw the skeleton
				renderer.drawSkeleton(this.skeleton, true);
				// Complete rendering.
				renderer.end();
			}
		}

		new spine.SpineCanvas(document.getElementById("canvas"), {
			app: new App()
		})
	</script>
</body>

</html>